package com.jpxx.netty.runtime;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;

import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicInteger;

import org.jboss.marshalling.MarshallerFactory;

public class Server {
	private int port;  

	public Server(int port) {  
		this.port = port;  
	}  

	
	public void start(){  
		 /***
         * NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器，
         * Netty提供了许多不同的EventLoopGroup的实现用来处理不同传输协议。
         * 在这个例子中我们实现了一个服务端的应用，
         * 因此会有2个NioEventLoopGroup会被使用。
         * 第一个经常被叫做‘boss’，用来接收进来的连接。
         * 第二个经常被叫做‘worker’，用来处理已经被接收的连接，
         * 一旦‘boss’接收到连接，就会把连接信息注册到‘worker’上。
         * 如何知道多少个线程已经被使用，如何映射到已经创建的Channels上都需要依赖于EventLoopGroup的实现，
         * 并且可以通过构造函数来配置他们的关系。
         */
		EventLoopGroup bossGroup = new NioEventLoopGroup(); 
		EventLoopGroup workerGroup = new NioEventLoopGroup();  
		try {  
			AtomicInteger index = new AtomicInteger(0); //原子整数
			
			ServerBootstrap sbs = new ServerBootstrap();
			sbs.group(bossGroup,workerGroup)
			.channel(NioServerSocketChannel.class)
			.option(ChannelOption.SO_BACKLOG, 1024)// 设置tcp缓冲区
			//.handler(new LoggingHandler(LogLevel.INFO))//日志
			.childHandler(new ChannelInitializer<SocketChannel>() {  
					@Override
					protected void initChannel(SocketChannel sc) throws Exception {  
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());//通到加上marshalling工具类
						sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());//通到加上marshalling工具类
						sc.pipeline().addLast(new ReadTimeoutHandler(5));//读写超过5秒 没有发送数据，就断开连接
						sc.pipeline().addLast(new ServerHandler());//加业务
					};  

			});
			
			// 绑定端口，开始接收进来的连接
			ChannelFuture future = sbs.bind(port).sync();    

			System.out.println("服务器开始监听 " + port );  
			future.channel().closeFuture().sync();  
		} catch (Exception e) {  
			bossGroup.shutdownGracefully();  
			workerGroup.shutdownGracefully();  
		}  
	}  

	public static void main(String[] args) throws Exception {
		int port;  
		if (args.length > 0) {  
			port = Integer.parseInt(args[0]);  
		} else {  
			port = 8765;
		}  
		new Server(port).start();  
	}  
}
